#  coding=utf-8
import traceback
from dataclasses import dataclass
from datetime import datetime

from sqlalchemy.sql.functions import now

from common.log import log
from .. import db


@dataclass(init=False)
class BaseModel(db.Model):
    __abstract__ = True
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    create_time = db.Column(db.DateTime, index=True, default=datetime.utcnow)
    update_time = db.Column(db.DateTime, index=True, default=datetime.utcnow)
    is_deleted = db.Column(db.SmallInteger, index=True, default=0)

    @classmethod
    def create(cls, parameters: dict = None):
        """
        新增
        :return: 无
        """
        return cls._add_item_by_params(parameters)

    @classmethod
    def update(cls, entry_id: int, parameters: dict = None):
        """
        更新
        :return: 无
        """
        return cls._update_by_id(entry_id, parameters)

    @classmethod
    def _get_by_params(cls, kwargs: dict = None):
        query = cls.query
        for key, val in kwargs.items():
            if hasattr(cls, key):
                query = query.filter(getattr(cls, key) == val)
        return query

    @classmethod
    def get_first(cls, parameters: dict = None):
        """
        查看
        :parameters key: 主键id
        :return: 结果
        """
        result = cls._get_by_params(parameters).first()
        if result is None:
            raise Exception('资源不存在')
        return result

    @classmethod
    def get_list(cls, parameters: dict = None):
        """
        查看
        :parameters key: 主键id
        :return: 结果
        """
        result = cls._get_by_params(parameters).all()
        if result is None:
            log.info(cls.__name__, '资源不存在')
        return result

    @classmethod
    def get_by_id(cls, key: int):
        """
        查看
        :param key: 主键id
        :return: 结果
        """
        result = cls.query.get(key)
        if result is None:
            log.info(cls.__name__, '资源不存在')
        return result

    @classmethod
    def _add_item_by_entry(cls, entry):
        msg = '新增{}'
        try:
            entry.create_time = now()
            entry.is_deleted = 0
            db.session.add(entry)
            db.session.commit()
            return True, msg.format('成功'), entry
        except:
            db.session.rollback()
            log.error(traceback.format_exc())
            return False, msg.format('失败'), None

    @classmethod
    def _add_item_by_params(cls, kwargs: dict = None):
        entry = cls()
        for k, v in kwargs.items():
            if hasattr(entry, k):
                setattr(entry, k, v)
        return cls._add_item_by_entry(entry)

    @classmethod
    def _update_by_id(cls, entry_id, kwargs: dict = None):
        entry = cls.get_by_id(entry_id)
        if not entry:
            return False, 'item i is not exit', ''

        kwargs.update({'update_time': now()})
        for k, v in kwargs.items():
            if hasattr(entry, k):
                setattr(entry, k, v)

        msg = '修改{}'
        if kwargs.get('is_deleted') == 1:
            entry.deleted = 1
            msg = '删除{}'
        else:
            entry.deleted = 0
        try:
            db.session.commit()
            return True, msg.format('成功'), entry
        except:
            db.session.rollback()
            log.error(traceback.format_exc())
            return False, msg.format('失败'), ''

    @classmethod
    def _delete_item_by_id(cls, entry_id: int):
        log.error('will delete ays_order_count item %s' % entry_id)
        entry = cls.get_by_id(entry_id)
        if not entry:
            return False, 'item i is not exit', ''

        entry.is_deleted = 1
        msg = '删除{}'
        try:
            db.session.commit()
            return True, msg.format('成功'), ''
        except:
            db.session.rollback()
            log.error(traceback.format_exc())
            return False, msg.format('失败'), ''

    @classmethod
    def delete(cls, key: int):
        """
        删除
        :param key: 主键id
        :return: 无
        """
        return cls._delete_item_by_id(key)
